/*
 * ssi_link_layer_ut.cpp
 *
 *  Created on: 3/10/2011
 *      Author: Santiago Carmona Meco
 */


#include <public/stdlib.h>
#include <public/string.h>
#include <public/stdio.h>
#include <public/ssi_link_layer.h>
#include <public/crc_16.h>
#include <public/ssi_link_layer_ut.h>
#include <public/config.h>
#include <public/debug_primitives.h>
#include <time.h>



#define MAX 100
#define NUM_PRUEBAS 200000


SSI_LINK_LAYER_UT Sii_Link_Layer_Ut("SSI_LINK_LAYER_UT", true, true, 0);


SSI_LINK_LAYER_UT::SSI_LINK_LAYER_UT(const char * id, bool_t priority, bool_t setSeed,
		int32_t seed) : CUTBase(id,priority, setSeed, seed)
{
	// TODO Auto-generated constructor stub

}

SSI_LINK_LAYER_UT::~SSI_LINK_LAYER_UT() {
	// TODO Auto-generated destructor stub
}

bool_t SSI_LINK_LAYER_UT::DoTest(void)
{
	byte_t tramaRecibida[50];
	byte_t tramaRecibidaSignal[17];
	struct ssi_link_layer_data_frame_info_t tramaFinal;
	struct ssi_link_layer_signal_frame_info_t tramaFinalSignal;
	int i=0,j=0,numero,caso;
	bool_t testCrcOk,testOk=1;



	init_CRC_word16_table();

	while (j<NUM_PRUEBAS)
	{
		/*Recepción de la trama*/
		srand (time(NULL));
		for (i=0;i<48;i++)
		{
			numero=(rand()%42);
			tramaRecibida[i]=(numero+48);
		}

		ssi_link_layer_add_crc_to_data_frame(tramaRecibida);//añadimos el CRC correspondiente a la trama generada aleatoriamente
		numero=rand()%48;
		caso=rand()%2;
		switch (caso)
		{
			case 0://trama falla
				tramaRecibida[numero]++;
				testCrcOk=ssi_link_layer_check_data_frame_crc(tramaRecibida);//chequeamos Crc
				//testCrcOk=0;
				tramaRecibida[numero]--;
				if (testCrcOk)//nunca debería dar true
					{
						DEBUG("CRC FAIL: ERROR");//CAMBIAR ESTOS MENSAJES
						testOk=0;
					}
				break;
			case 1://trama recibida correctamente
				testCrcOk=ssi_link_layer_check_data_frame_crc(tramaRecibida);//chequeamos Crc
				//testCrcOk=1;
				/*guardamos en nuestra estructura los valores correspondientes de la trama*/
				if (!testCrcOk)
					{
						DEBUG("CORRECT FRAME: CRC ERROR");
						testOk=0;
					}
				else
				{
					ssi_link_layer_get_data_frame_info (tramaRecibida,&tramaFinal);
					/*comprobamos que se han obtenido correctamente los valores*/
					if(!Check_Data_Frame_Info (tramaRecibida,tramaFinal))//esta función ya imprime en el caso de fallar algún campo
					{
						testOk=0;
					}
				}
				break;
		}

		j++;
	}
	j=0;
	while (j<NUM_PRUEBAS)
		{
			/*Recepción de la trama*/
			srand (time(NULL));
			for (i=0;i<15;i++)
			{
				numero=(rand()%42);
				tramaRecibidaSignal[i]=(numero+48);
			}

			ssi_link_layer_add_crc_to_signal_frame(tramaRecibidaSignal);//añadimos el CRC correspondiente a la trama generada aleatoriamente
			numero=rand()%15;
			caso=rand()%2;
			switch (caso)
			{
				case 0://trama falla
					tramaRecibidaSignal[numero]++;
					testCrcOk=ssi_link_layer_check_signal_frame_crc(tramaRecibidaSignal);//chequeamos Crc
					//testCrcOk=0;
					tramaRecibidaSignal[numero]--;
					if (testCrcOk)//nunca debería dar true
						{
							DEBUG("CRC FAIL: ERROR");//CAMBIAR ESTOS MENSAJES
							testOk=0;
						}
					break;
				case 1://trama recibida correctamente
					testCrcOk=ssi_link_layer_check_signal_frame_crc(tramaRecibidaSignal);//chequeamos Crc
					//testCrcOk=1;
					/*guardamos en nuestra estructura los valores correspondientes de la trama*/
					if (!testCrcOk)
						{
							DEBUG("CORRECT FRAME: CRC ERROR");
							testOk=0;
						}
					else
					{
						ssi_link_layer_get_signal_frame_info (tramaRecibidaSignal,&tramaFinalSignal);
						/*comprobamos que se han obtenido correctamente los valores*/
						if(!Check_Signal_Frame_Info (tramaRecibidaSignal,tramaFinalSignal))//esta función ya imprime en el caso de fallar algún campo
						{
							testOk=0;
						}
					}
					break;
			}

			j++;
		}
	/*Envio de trama*///TODO:montar tramas al principio con esta funcion
	//ssi_link_layer_build_frame(tramaEnviada,&tramaFinal);//tramaEnviada se forma con los datos e tramaFinal
	return testOk;

}

bool_t SSI_LINK_LAYER_UT::Check_Radio_Id(byte_t * pFrame, byte_t *pRadioId)
{
	int i=0;

	while (i<6)
	{
		if (!CompareByte(pRadioId[i],pFrame[i],"error Radio Id"))
		{
			return 0;
		}
		i++;
	}
	return 1;
}


bool_t SSI_LINK_LAYER_UT::Check_Sensor_Id(byte_t * pFrame, word16_t SensorId)
{
	word16_t sensorIdAux=0;

	sensorIdAux=pFrame[6];
	sensorIdAux=sensorIdAux<<8;
	sensorIdAux=sensorIdAux+pFrame[7];

	return 	CompareWord16(sensorIdAux,SensorId,"error Sensor Id");
}

bool_t SSI_LINK_LAYER_UT::Check_Flags(byte_t * pFrame, byte_t flags)
{
	return 	CompareByte(pFrame[8],flags,"error Flags");
}

bool_t SSI_LINK_LAYER_UT::Check_Reserved(byte_t * pFrame, byte_t *pReserved)
{
	int i=0;

	while (i<6)
	{
		if (!CompareByte(pReserved[i],pFrame[9+i],"error Reserved"))
		{
			return 0;
		}
		i++;
	}
	return 1;
}

bool_t SSI_LINK_LAYER_UT::Check_Length(byte_t * pFrame, byte_t lenght)
{
	return 	CompareByte(pFrame[15],lenght,"error Length");
}


bool_t SSI_LINK_LAYER_UT::Check_Data(byte_t * pFrame, byte_t *pData)
{
	int i=0;

	while (i<32)
	{
		if (!CompareByte(pData[i],pFrame[16+i],"error Data"))
		{
			return 0;
		}
		i++;
	}
	return 1;
}

bool_t SSI_LINK_LAYER_UT::Check_Data_Frame_Info(byte_t * pFrame,struct ssi_link_layer_data_frame_info_t frameInfo)
{
	if(!Check_Radio_Id(pFrame,frameInfo.radio_id) 	||
	   !Check_Sensor_Id(pFrame,frameInfo.sensor_id) ||
	   !Check_Flags(pFrame,frameInfo.flags)	||
	   !Check_Reserved(pFrame,frameInfo.reserved) ||
	   !Check_Length(pFrame,frameInfo.length)      ||
	   !Check_Data(pFrame,frameInfo.data))
	{
		return 0;
	}
	else
	{
		return 1;
	}
}

bool_t SSI_LINK_LAYER_UT::Check_Signal_Frame_Info(byte_t * pFrame,struct ssi_link_layer_signal_frame_info_t frameInfo)
{
	if(!Check_Radio_Id(pFrame,frameInfo.radio_id) 	||
	   !Check_Sensor_Id(pFrame,frameInfo.sensor_id) ||
	   !Check_Flags(pFrame,frameInfo.flags)	||
	   !Check_Reserved(pFrame,frameInfo.reserved))
	{
		return 0;
	}
	else
	{
		return 1;
	}
}
